﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.ExpressionParsing;
using System.Reflection;
using Common;

namespace Service.BusinessLogic
{
    public abstract class BaseBusinessLogicVisitorExtension : IFunctionVisitorExtension
    {
        protected Object CurrentBusinessEntity { get; set; }
        protected DateTime TimeStamp { get; set; }

        protected String FunctionIdentifier { get; set; }
        protected LogicalExpression[] FunctionParameters { get; set; }
        protected LogicalExpressionVisitor Visitor { get; set; }


        protected BaseBusinessLogicVisitorExtension(Object currentBusinessEntity, DateTime timeStamp)
        {
            CurrentBusinessEntity = currentBusinessEntity;
            TimeStamp = timeStamp;
        }

        public T GetArgValue<T>(Int32 index)
        {
            FunctionParameters[index].Accept(Visitor);
            T result = (T)Visitor.Result;
            return result;
        }

        #region IFunctionVisitorExtension members

        public IList<String> Identifiers
        {
            get 
            {
                IList<String> result = new List<String>();

                foreach (MethodInfo mi in GetType().GetMethods())
                {
                    if (!ReflectionHelper.HasAttribute(mi, typeof(FunctionExtensionAttribute)))
                        continue;

                    FunctionExtensionAttribute attr = mi.GetCustomAttributes(typeof(FunctionExtensionAttribute), false)[0]
                        as FunctionExtensionAttribute;

                    result.Add(attr.FunctionIdentifier);
                }

                return result;
            }
        }

        public object Execute(string functionIdentifier, LogicalExpression[] functionParameters, LogicalExpressionVisitor visitor)
        {
            FunctionIdentifier = functionIdentifier;
            FunctionParameters = functionParameters;
            Visitor = visitor;

            MethodInfo targetMI = null;

            foreach (MethodInfo mi in GetType().GetMethods())
            {
                if (!ReflectionHelper.HasAttribute(mi, typeof(FunctionExtensionAttribute)))
                    continue;

                FunctionExtensionAttribute attr = mi.GetCustomAttributes(typeof(FunctionExtensionAttribute), false)[0]
                    as FunctionExtensionAttribute;

                if (functionIdentifier.ToLower() == attr.FunctionIdentifier.ToLower())
                {
                    targetMI = mi;
                    break;
                }
            }

            return targetMI.Invoke(this, null);
        }

        #endregion IFunctionVisitorExtension members
    }
}
